home *** CD-ROM | disk | FTP | other *** search
Text File | 2000-09-28 | 30.8 KB | 1,413 lines | [TEXT/MPS ] |
- /*
- File: SprocketInvaders.c
-
- Contains: xxx put contents here xxx
-
- Version: xxx put version here xxx
-
- Copyright: © 1998-1999 by Apple Computer, Inc., all rights reserved.
-
- File Ownership:
-
- DRI: xxx put dri here xxx
-
- Other Contact: xxx put other contact here xxx
-
- Technology: xxx put technology here xxx
-
- Writers:
-
- (cjd) Chris De Salvo
- (cjd) Chris DeSalvo
- (BWS) Brent Schorsch
-
- Change History (most recent first):
-
- <SP20> 3/3/99 cjd Change player shot/CD controls code so that shots go through CD
- controls.
- <SP19> 1/29/99 cjd Added code for new CD controller sprites.
- <SP18> 1/21/99 cjd Removing 68K build code
- <17> 7/2/98 BWS fix 68k build (no SSp toggle)
- <16> 7/1/98 cjd Made it so that you can shoot enemy shots, added optimization
- for collission of player shots and enemies, added new FPS
- display for SSp usage.
- <15> 6/12/98 BWS InputSprocket 68k now used
- */
-
- //• ------------------------------------------------------------------------------------------ •
- //•
- //• Copyright © 1996 Apple Computer, Inc., All Rights Reserved
- //•
- //•
- //• You may incorporate this sample code into your applications without
- //• restriction, though the sample code has been provided "AS IS" and the
- //• responsibility for its operation is 100% yours. However, what you are
- //• not permitted to do is to redistribute the source as "DSC Sample Code"
- //• after having made changes. If you're going to re-distribute the source,
- //• we require that you make it clear in the source that the code was
- //• descended from Apple Sample Code, but that you've made changes.
- //•
- //• Authors:
- //• Chris De Salvo
- //• Jamie Osborne
- //• Michael Evans
- //• Tim Carroll
- //•
- //• ------------------------------------------------------------------------------------------ •
-
- //• ------------------------------ Includes
-
- #include <Fonts.h>
- #include <stdio.h>
- #include <string.h>
-
- #include "ErrorHandler.h"
- #include "EventHandler.h"
- #include "GameObject.h"
- #include "Graphics.h"
- #include "MoviePlayback.h"
- #include "ObjectActions.h"
- #include "CD_Utils.h"
- #include "SIResources.h"
- #include "SoundHandler.h"
- #include "SprocketInvaders.h"
- #include "Sprite.h"
- #include "NetSprocketSupport.h"
- #include "CommonStuff.h"
-
- //• ------------------------------ Private Definitions
-
- #define RAND(x) ((Random() & 0x7FFF) % (x))
-
- #define kPlayerVelocity 2L //• Speed at which player moves
- #define kPlayerShotVelocity 10L //• Speed at which player shots travel
- #define kPointsVelocity -2L //• Vertical speed of the "points" object (negative is up)
- #define kEnemyVelocity 5L //• Speed at which enemies move
- #define kEnemyShotVelocity 4L //• Speed at which enemy shots drop
-
- #define kEnemyOffset 8 //• Space between columns of enemies
-
- #define kEnemyParticleColor 200
- #define kPlayerParticleColor 192
- #define kPlasmaParticleColor 208
- #define kMissileParticleColor 216
-
- //• ------------------------------ Private Types
-
- enum
- {
- scPlayer,
- scPlayer2,
- scPlayerShot,
- scPoints,
- scEnemy,
- scEnemyShot,
- scPlayButton,
- scStopButton,
- scPrevButton,
- scSkipButton,
- scNumSprites
- };
-
- //• ------------------------------ Private Variables
-
- static SpritePtr gSpriteCache[scNumSprites]; //• Sprite artwork is cached here so that multiple items using
- //• the same artwork only need one copy.
-
- static UInt32 gWave; //• Current level number
- static UInt32 gEnemyGas; //• Number of enemies that get updated per game loop
- static SInt32 gEnemyNewDirection; //• If enemies changed directions, this is the new direction
- static UInt32 gFrameRateBaseTime; //• Base time for this game to count frame rate
-
- static float gGreenAccum;
- static float gRedAccum;
-
- //• ------------------------------ Private Functions
-
- static void AddPlayers(void);
- static void AddEnemies(void);
- static void CollideShotsToEnemies(void);
- static void CollideShotsToPlayers(void);
- static void CollideShotsToShots(void);
- static void AddCDControls(void);
- static void AddPoints(short x, short y);
- static void DisplayGameOver(CGrafPtr backBuff);
- static void DropEnemies(void);
- static void AdvanceEnemies(void);
- static void DisplayFrameRate(void);
- static void EndGame(CGrafPtr backBuff);
- static void GetGreenInput(void);
- static void GetRedInput(void);
- static Boolean WasButtonHit (ISpElementReference inElement);
- static void BuildEnemyRect(void);
- static void DoCDAction(UInt32 inAction);
- static void CollideShotsToCDControls(void);
-
- //• ------------------------------ Public Variables
-
- Boolean gGameInProgress = false;
- Boolean gTwoPlayers = false;
-
- GameObjectPtr gEnemyList = nil; //• List of enemies
- GameObjectPtr gEnemyShotList = nil; //• List of enemy shots
- GameObjectPtr gPlayerList = nil; //• List of players
- GameObjectPtr gGreenPlayerShotList = nil; //• List of green player shots
- GameObjectPtr gRedPlayerShotList = nil; //• List of red player shots
- GameObjectPtr gMiscObjectList = nil; //• List of misc items (score sprites, etc)
-
- Rect gEnemyRect; //• Rect enclosing all enemies
-
- UInt32 gEnemyTask;
- SInt32 gEnemiesChangeDirection;
- SInt32 gEnemyVelocity;
- UInt32 gNumEnemies;
-
- UInt32 gEnemyLevel;
- UInt32 gNumEnemiesProcessed;
-
- UInt32 gNumGreenPlayerLives = 0;
- UInt32 gNumRedPlayerLives = 0;
-
- Boolean gNetPlay;
-
- //• -------------------- InitNewRound
-
- static void
- InitNewRound(UInt32 wave)
- {
- SInt16 numCDTracks;
-
- //• Flush out our object lists
- GameObjectDisposeList(&gEnemyList);
- GameObjectDisposeList(&gEnemyShotList);
- GameObjectDisposeList(&gPlayerList);
- GameObjectDisposeList(&gGreenPlayerShotList);
- GameObjectDisposeList(&gRedPlayerShotList);
- GameObjectDisposeList(&gMiscObjectList);
-
- //• Add our initial objects
- AddPlayers();
- AddEnemies();
-
- if (true == gCDAudio)
- AddCDControls();
-
- gEnemyTask = kEnemyMovingRight;
- gEnemiesChangeDirection = 0;
- gEnemyVelocity = kEnemyVelocity;
- gEnemyLevel = 1;
- gWave = wave;
-
- if (true == gCDAudio)
- {
- //• Pick a CD audio track and start playback if CD audio was chosen
- numCDTracks = CD_GetNumTracks();
-
- if (numCDTracks > 0)
- {
- SInt16 trackNum;
-
- if (wave > numCDTracks)
- {
- trackNum = (wave % numCDTracks) + 1;
- }
- else
- {
- trackNum = wave;
- }
-
- //• Unnecessary error checking
- if (trackNum < 1)
- trackNum = 1;
-
- if (trackNum > numCDTracks)
- trackNum = numCDTracks;
-
- CD_PlayAudioTrack(trackNum, playmodeStereo, true);
- }
- }
-
- SetRect(&gEnemyRect, 0, 0, 0, 0);
- }
-
- //• -------------------- NextRound
-
- static void
- NextRound(void)
- {
- InitNewRound(gWave + 1);
- }
-
-
- //• -------------------- InitNewGame
-
- void
- InitNewGame(UInt32 wave)
- {
- UInt32 i;
-
- //• Start up the background movie if one was chosen
- PlaybackMovie();
-
- for (i = 0; i < numInputs; i++)
- ISpElement_Flush(gInputElements[i]);
-
- gGreenAccum = 0;
- gRedAccum = 0;
-
- gGameInProgress = true;
- gFrameRateBaseTime = 0L;
-
- //• Flush out the sprite cache and load in the new sprites
- for (i = 0; i < scNumSprites; i++)
- SpriteDispose(&(gSpriteCache[i]));
-
- gSpriteCache[scPlayer] = SpriteLoad(kSPRTPlayer);
- if (! gSpriteCache[scPlayer])
- FatalError("Could not load player tank.");
-
- gSpriteCache[scPlayer2] = SpriteLoad(kSPRTPlayer2);
- if (! gSpriteCache[scPlayer])
- FatalError("Could not load player 2 tank.");
-
- gSpriteCache[scPlayerShot] = SpriteLoad(kSPRTPlayerShot);
- if (! gSpriteCache[scPlayerShot])
- FatalError("Could not load player shot.");
-
- gSpriteCache[scPoints] = SpriteLoad(kSPRTPoints);
- if (! gSpriteCache[scPoints])
- FatalError("Could not load points.");
-
- gSpriteCache[scEnemy] = SpriteLoad(kSPRTEnemy);
- if (! gSpriteCache[scEnemy])
- FatalError("Could not load enemy.");
-
- gSpriteCache[scEnemyShot] = SpriteLoad(kSPRTEnemyShot);
- if (! gSpriteCache[scEnemyShot])
- FatalError("Could not load enemy shot.");
-
- gSpriteCache[scPlayButton] = SpriteLoad(kSPRTPlayButton);
- if (! gSpriteCache[scPlayButton])
- FatalError("Could not load play button.");
-
- gSpriteCache[scStopButton] = SpriteLoad(kSPRTStopButton);
- if (! gSpriteCache[scStopButton])
- FatalError("Could not load stop button.");
-
- gSpriteCache[scPrevButton] = SpriteLoad(kSPRTPrevButton);
- if (! gSpriteCache[scPrevButton])
- FatalError("Could not load prev button.");
-
- gSpriteCache[scSkipButton] = SpriteLoad(kSPRTSkipButton);
- if (! gSpriteCache[scSkipButton])
- FatalError("Could not load skip button.");
-
- gNumGreenPlayerLives = 3;
-
- if (gTwoPlayers)
- gNumRedPlayerLives = 3;
- else
- gNumRedPlayerLives = 0;
-
- //• Activate our graphics context and tell InputSprocket to start
- //• watching our controllers
- GraphicsActive();
- ISpResume();
-
- InitNewRound(wave);
- }
-
- #pragma mark -
-
- //• -------------------- GameLoop
-
- void
- GameLoop(void)
- {
- CGrafPtr backBuff;
- ISpElementEvent event;
- Boolean wasEvent;
-
- if (WasButtonHit(gInputElements[soundToggle]))
- gSoundEffects = !gSoundEffects;
-
- if (gNetPlay)
- {
- if (gIAmHost)
- {
- GetGreenInput();
- SendInputState(gGameKeys.greenLeft, gGameKeys.greenRight, gGameKeys.greenFire);
- GetRedInput();
- }
- else
- {
- GetRedInput();
- SendInputState(gGameKeys.redLeft, gGameKeys.redRight, gGameKeys.redFire);
- GetGreenInput();
- }
- }
- else
- {
- GetGreenInput();
- if (gTwoPlayers)
- GetRedInput();
- }
-
-
- //• Load in the current SoundSprocket throttle value
- ISpElement_GetSimpleState(gInputElements[soundSprocketThrottle], &gCPUCurrentLoad);
-
- if (0 == gCPULoadModifier)
- gCPUCurrentLoad = 0;
- else
- gCPUCurrentLoad /= gCPULoadModifier;
-
- //• Perform player/missile collission detection
- CollideShotsToCDControls();
- CollideShotsToEnemies();
- CollideShotsToShots();
- CollideShotsToPlayers();
-
- //• If any enemy hit a boundry on the last run, switch directions
- if (gEnemiesChangeDirection)
- {
- DropEnemies();
- gEnemiesChangeDirection = 0;
- gEnemyTask = kEnemyDropping;
- }
-
- //• gEnemyGas determines how many aliens are processed each game loop
- //• This gives the staggered updating on the screen. It also speeds up the
- //• alien movement and shooting speed as the game progresses.
- gEnemyGas = gWave + 1;
-
- ServiceMoviePlayback();
-
- //• Get a reference to the back buffer so we can draw into it
- DSpContext_GetBackBuffer(gDisplayContext, kDSpBufferKind_Normal, &backBuff);
-
- //• Check the abort key in case the user wishes to quit out early
- ISpElement_GetNextEvent(gInputElements[abort], sizeof (event), &event, &wasEvent);
- if (gGotEndGameMessage || (wasEvent && (event.data == kISpButtonDown)))
- {
- if (gNetPlay && !gGotEndGameMessage)
- SendEndGame();
-
- EndGame(backBuff);
- return;
- }
-
- //• Have all game objects perform their actions
- AdvanceEnemies();
- GameObjectListAdvance(gPlayerList);
- GameObjectListAdvance(gEnemyShotList);
- GameObjectListAdvance(gGreenPlayerShotList);
- GameObjectListAdvance(gRedPlayerShotList);
- GameObjectListAdvance(gMiscObjectList);
-
- //• Draw all game objects
- GameObjectListDraw(gEnemyList, backBuff);
- GameObjectListDraw(gPlayerList, backBuff);
- GameObjectListDraw(gEnemyShotList, backBuff);
- GameObjectListDraw(gGreenPlayerShotList, backBuff);
- GameObjectListDraw(gRedPlayerShotList, backBuff);
- GameObjectListDraw(gMiscObjectList, backBuff);
-
- //• Build a master rect of all the enemies to help optimize hit testing
- //• the next time through the loop.
- BuildEnemyRect();
-
- //• Check for end of wave/game
- if ((gNumGreenPlayerLives < 1) && (gNumRedPlayerLives < 1))
- {
- EndGame(backBuff);
- return;
- }
-
- //• If we just killed the last enemy then start the next round
- if (gNumEnemies < 1)
- {
- NextRound();
- }
-
- //• Update the frame rate display information
- DisplayFrameRate();
-
- //• Redraw the entire screen. This is done last so that if the game over screen was drawn it gets blit for free
- GraphicsUpdateScreen();
-
- }
-
- //• -------------------- GetAutoFireButton
-
- static Boolean
- GetAutoFireButton(ISpElementReference inElement)
- {
- OSStatus error;
- UInt32 input;
- Boolean wasEvent;
- Boolean fire = false;
-
- //• poll
- error = ISpElement_GetSimpleState(inElement, &input);
- if (! error && (input == kISpButtonDown))
- fire = true;
-
- //• but don't miss fast clicks or macros
- do
- {
- ISpElementEvent event;
-
- error = ISpElement_GetNextEvent(inElement, sizeof(ISpElementEvent), &event, &wasEvent);
-
- if (! error && wasEvent && (event.data == kISpButtonDown))
- {
- fire = true;
- break;
- }
- } while (wasEvent && !error);
-
- //• flush the queue
- ISpElement_Flush(inElement);
-
- return (fire);
- }
-
- //• -------------------- WasButtonHit
-
- static Boolean
- WasButtonHit (ISpElementReference inElement)
- {
- OSStatus error;
- Boolean wasEvent;
- Boolean down = false;
-
- do
- {
- ISpElementEvent event;
-
- error = ISpElement_GetNextEvent(inElement, sizeof(ISpElementEvent), &event, &wasEvent);
-
- if (! error && wasEvent && (event.data == kISpButtonDown))
- {
- down = true;
- break;
- }
- } while (wasEvent && !error);
-
- return (down);
- }
-
- //• -------------------- GetGreenInput
-
- void
- GetGreenInput(void)
- {
- UInt32 input;
-
- if (! gNetPlay || (gNetPlay && gIAmHost)) // in netplay, the host is the green player, and the joiner the red
- {
- //• Check the movement axis
- ISpElement_GetSimpleState(gInputElements[greenMovement], &input);
-
- gGameKeys.greenLeft = false;
- gGameKeys.greenRight = false;
-
- if (input < 0x2FFFFFFF)
- {
- gGameKeys.greenLeft = true;
- }
- else if (input > 0xBFFFFFFF)
- {
- gGameKeys.greenRight = true;
- }
- else if (input < 0x5FFFFFFF)
- {
- gGreenAccum += ((float) input - (float) 0x5FFFFFFF) / (float) 0x3FFFFFFF;
- if (gGreenAccum < -1)
- {
- gGameKeys.greenLeft = true;
- gGreenAccum += 1;
- }
- }
- else if (input > 0x9FFFFFFF)
- {
- gGreenAccum += ((float) input - (float) 0x9FFFFFFF) / (float) 0x3FFFFFFF;
- if (gGreenAccum > 1)
- {
- gGameKeys.greenRight = true;
- gGreenAccum -= 1;
- }
- }
-
- //• Check the fire button
- gGameKeys.greenFire = GetAutoFireButton(gInputElements[greenFire]);
- }
- else if (gNetPlay && !gIAmHost) //• wait for player 1's input
- {
- gReceivedInput = false;
- while (! gReceivedInput && !gGotEndGameMessage)
- HandleNetworking();
- }
- }
-
- //• -------------------- GetRedInput
-
- void GetRedInput(void)
- {
- UInt32 input;
-
- if (! gNetPlay || (gNetPlay && !gIAmHost)) // in netplay, the host is the green player, and the joiner the red
- {
- //• Check the movement axis
- ISpElement_GetSimpleState(gInputElements[redMovement], &input);
-
- gGameKeys.redLeft = false;
- gGameKeys.redRight = false;
-
- if (input < 0x3FFFFFFF)
- {
- gGameKeys.redLeft = true;
- }
- else if (input > 0xAFFFFFFF)
- {
- gGameKeys.redRight = true;
- }
- else if (input < 0x5FFFFFFF)
- {
- gRedAccum += ((float) input - (float) 0x5FFFFFFF) / (float) 0x2FFFFFFF;
- if (gRedAccum < -1)
- {
- gGameKeys.redLeft = true;
- gRedAccum += 1;
- }
- }
- else if (input > 0x9FFFFFFF)
- {
- gRedAccum += ((float) input - (float) 0x9FFFFFFF) / (float) 0x2FFFFFFF;
- if (gRedAccum > 1)
- {
- gGameKeys.redRight = true;
- gRedAccum -= 1;
- }
- }
-
- //• Check the fire button
- gGameKeys.redFire = GetAutoFireButton(gInputElements[redFire]);
- }
- else if (gNetPlay && gIAmHost) //• wait for player 2's input
- {
- gReceivedInput = false;
- while (! gReceivedInput && !gGotEndGameMessage)
- HandleNetworking();
- }
- }
-
- //• -------------------- PlayerShoot
-
- void
- PlayerShoot(GameObjectPtr whichPlayer)
- {
- Rect r;
- GameObjectPtr go;
- GameObjectPtr shotList;
-
-
- if (whichPlayer->kind == objectGreenPlayer)
- {
- if (gGreenPlayerShotList)
- return;
- else
- shotList = gGreenPlayerShotList;
- }
- else
- {
- if (gRedPlayerShotList)
- return;
- else
- shotList = gRedPlayerShotList;
- }
-
- SoundHandlerPlay(soundPlayerFire, whichPlayer->screenX, whichPlayer->screenY);
-
- go = GameObjectAllocate();
- if (! go)
- FatalError("Could not allocate player shot.");
-
- GameObjectAddToList(&shotList, go);
-
- SetRect(&r, 20, 0, 620, 0);
- GameObjectSetBounds(go, &r);
- GameObjectSetSprite(go, gSpriteCache[scPlayerShot]);
-
- go->screenX = whichPlayer->screenX;
- go->screenY = whichPlayer->screenY - SpriteHeight(whichPlayer->objectData.sprite, whichPlayer->frame) - 1;
- go->velocityH = 0;
- go->velocityV = kPlayerShotVelocity;
- go->action = PlayerShotAction;
-
- if (whichPlayer->kind == objectRedPlayer)
- {
- go->kind = objectRedPlayerShot;
- if (! gRedPlayerShotList)
- gRedPlayerShotList = shotList;
- }
- else
- {
- go->kind = objectGreenPlayerShot;
- if (! gGreenPlayerShotList)
- gGreenPlayerShotList = shotList;
- }
- }
-
- //• -------------------- AdvanceEnemies
-
- static void
- AdvanceEnemies(void)
- {
- GameObjectPtr current, next;
- UInt32 oldProcessed;
-
- //• This set of loops makes sure that gEnemyGas worth
- //• of aliens get processed this loop. If gEnemyGas is set to
- //• 10, and there are only 5 aliens left then they all update twice
- //• for a total of ten updates. This is how we take care us speeeding
- //• the aliens up as fewer and fewer of them are present.
-
- do
- {
- gNumEnemiesProcessed = 0;
- current = gEnemyList;
-
- do
- {
- oldProcessed = gNumEnemiesProcessed;
- next = current->next;
- current->action(current);
-
- //• If we moved an alien, use up some alien gas
- if (oldProcessed != gNumEnemiesProcessed)
- gEnemyGas--;
-
- current = next;
- } while (next && gEnemyGas);
-
- //• If no enemies were processed then they're all at the same level, so move on
- if (gNumEnemiesProcessed == 0)
- {
- gEnemyLevel++;
-
- if (gEnemyTask == kEnemyDropping)
- gEnemyTask = gEnemyNewDirection;
- }
-
- } while (gEnemyGas && (gNumEnemies > 0));
- }
-
- //• -------------------- DropEnemies
-
- static void
- DropEnemies(void)
- {
- GameObjectPtr current, next;
-
- //• One of the enemies hit the edge of their boundary so we need
- //• to draw them all one row.
- gEnemyNewDirection = gEnemiesChangeDirection;
-
- do
- {
- current = gEnemyList;
- gNumEnemiesProcessed = 0;
-
- do
- {
- next = current->next;
- current->action(current);
- current = next;
- } while (next);
- } while (gNumEnemiesProcessed);
-
- gEnemyLevel++;
- }
-
- //• -------------------- EnemyShoot
-
- void
- EnemyShoot(GameObjectPtr whichEnemy)
- {
- Rect r;
- GameObjectPtr go;
-
- //• Create a game object for the shot
- go = GameObjectAllocate();
- if (! go)
- FatalError("Could not allocate enemy shot.");
-
- //• Play the alien shooting sound effect
- SoundHandlerPlay(soundEnemyFire, whichEnemy->screenX, whichEnemy->screenY);
-
- //• Add the shot to the enemy shot list
- GameObjectAddToList(&gEnemyShotList, go);
-
- //• Set the attributes for this object
- SetRect(&r, 20, 0, 620, 412);
- GameObjectSetBounds(go, &r);
- GameObjectSetSprite(go, gSpriteCache[scEnemyShot]);
-
- go->screenX = whichEnemy->screenX;
- go->screenY = whichEnemy->screenY + 1;
- go->velocityH = 0;
- go->velocityV = kEnemyShotVelocity;
- go->action = EnemyShotAction;
- }
-
- //• -------------------- CollideShotsToCDControls
-
- static void
- CollideShotsToCDControls(void)
- {
- GameObjectPtr shot;
- GameObjectPtr target;
-
- if (false == gCDAudio)
- return;
-
- if (nil == gMiscObjectList)
- return;
-
- //• Iterate over the green player shots
- if (gGreenPlayerShotList)
- {
- for (shot = gGreenPlayerShotList; shot; shot = shot->next)
- {
- //• Iterate over the controls
- for (target = gMiscObjectList; target; target = target->next)
- {
- if (target->refCon < scPlayButton || target->refCon > scSkipButton)
- continue;
-
- if (IntersectRects(&shot->screenRect, &target->screenRect))
- DoCDAction(target->refCon);
- }
- }
- }
-
- //• Iterate over the red player shots
- if (gRedPlayerShotList)
- {
- for (shot = gRedPlayerShotList; shot; shot = shot->next)
- {
- //• Iterate over the controls
- for (target = gMiscObjectList; target; target = target->next)
- {
- if (target->refCon < scPlayButton || target->refCon > scSkipButton)
- continue;
-
- if (IntersectRects(&shot->screenRect, &target->screenRect))
- DoCDAction(target->refCon);
- }
- }
- }
- }
-
- //• -------------------- CollideShotsToEnemies
-
- static void
- CollideShotsToEnemies(void)
- {
- GameObjectPtr shot;
- GameObjectPtr target;
- Rect dummyRect;
-
- if (! gEnemyList)
- return;
-
- //• Iterate over the green player shots
- if (gGreenPlayerShotList)
- {
- for (shot = gGreenPlayerShotList; shot; shot = shot->next)
- {
- //• Quick easy check to see if the shot is even within the block of enemies
- if (false == SectRect(&shot->screenRect, &gEnemyRect, &dummyRect))
- continue;
-
- //• Iterate over the enemies
- for (target = gEnemyList; target; target = target->next)
- {
- if (IntersectRects(&shot->screenRect, &target->screenRect))
- {
- SoundHandlerPlay(soundEnemyHit, target->screenX, target->screenY);
-
- shot->action = PlayerShotDestroy;
- target->action = EnemyDestroy;
- AddPoints(target->screenX, target->screenY);
- }
- }
- }
- }
-
- //• Iterate over the red player shots
- if (gRedPlayerShotList)
- {
- for (shot = gRedPlayerShotList; shot; shot = shot->next)
- {
- //• Quick easy check to see if the shot is even within the block of enemies
- if (false == SectRect(&shot->screenRect, &gEnemyRect, &dummyRect))
- continue;
-
- //• Iterate over the enemies
- for (target = gEnemyList; target; target = target->next)
- {
- if (IntersectRects(&shot->screenRect, &target->screenRect))
- {
- SoundHandlerPlay(soundEnemyHit, target->screenX, target->screenY);
-
- shot->action = PlayerShotDestroy;
- target->action = EnemyDestroy;
- AddPoints(target->screenX, target->screenY);
- }
- }
- }
- }
- }
-
- //• -------------------- CollideShotsToShots
-
- static void
- CollideShotsToShots(void)
- {
- GameObjectPtr shot;
- GameObjectPtr target;
-
- if (nil == gEnemyShotList)
- return;
-
- //• Iterate over the green player shots
- if (gGreenPlayerShotList)
- {
- for (shot = gGreenPlayerShotList; shot; shot = shot->next)
- {
- //• Iterate over the enemies
- for (target = gEnemyShotList; target; target = target->next)
- {
- if (IntersectRects(&shot->screenRect, &target->screenRect))
- {
- shot->action = PlayerShotDestroy;
- target->action = EnemyShotDestroy;
- }
- }
- }
- }
-
- //• Iterate over the red player shots
- if (gRedPlayerShotList)
- {
- for (shot = gRedPlayerShotList; shot; shot = shot->next)
- {
- //• Iterate over the enemies
- for (target = gEnemyShotList; target; target = target->next)
- {
- if (IntersectRects(&shot->screenRect, &target->screenRect))
- {
- SoundHandlerPlay(soundEnemyHit, target->screenX, target->screenY);
-
- shot->action = PlayerShotDestroy;
- target->action = EnemyShotDestroy;
- }
- }
- }
- }
- }
- //• -------------------- CollideShotsToPlayers
-
- static void
- CollideShotsToPlayers(void)
- {
- GameObjectPtr shot;
- GameObjectPtr target;
- GameObjectPtr next;
-
- if (! gEnemyShotList || ! gPlayerList)
- return;
-
- target = gPlayerList;
- next = target->next;
-
- while (target != nil)
- {
- if (target->refCon > 0)
- return;
-
- //• Iterate over the enemy shots
- for (shot = gEnemyShotList; shot; shot = shot->next)
- {
- if (IntersectRects(&shot->screenRect, &target->screenRect))
- {
- SoundHandlerPlay(soundPlayerHit,target->screenX, target->screenY);
-
- shot->action = EnemyShotDestroy;
- target->action = PlayerDestroy;
-
- if (target->kind == objectGreenPlayer)
- {
- gNumGreenPlayerLives--;
- if (gNumGreenPlayerLives < 1)
- GameObjectRemoveFromList(&gPlayerList, target);
- }
- else
- {
- gNumRedPlayerLives--;
- if (gNumRedPlayerLives < 1)
- GameObjectRemoveFromList(&gPlayerList, target);
- }
- }
- }
-
- target = next;
- next = target->next;
- }
- }
-
- //• -------------------- BuildEnemyRect
-
- static void
- BuildEnemyRect(void)
- {
- Rect workingRect = { 0, 0, 0, 0 };
- GameObjectPtr currentEnemy;
-
- if (nil != gEnemyList)
- currentEnemy = gEnemyList;
- else
- return;
-
- workingRect = currentEnemy->screenRect;
-
- do
- {
- UnionRect(&workingRect, ¤tEnemy->screenRect, &workingRect);
- currentEnemy = currentEnemy->next;
- } while (nil != currentEnemy);
-
- gEnemyRect = workingRect;
- }
-
- #pragma mark -
-
- //• -------------------- AddPlayers
-
- static void
- AddPlayers(void)
- {
- Rect r;
- GameObjectPtr go;
-
- go = GameObjectAllocate();
- if (! go)
- FatalError("Could not allocate player object.");
-
- GameObjectAddToList(&gPlayerList, go);
-
- SetRect(&r, 20, 0, 620, 0);
- GameObjectSetBounds(go, &r);
- GameObjectSetSprite(go, gSpriteCache[scPlayer]);
-
- go->kind = objectGreenPlayer;
- go->screenX = 20;
- go->screenY = 412;
- go->velocityH = kPlayerVelocity;
- go->velocityV = 0;
- go->action = GreenPlayerAction;
-
- //• Sloppy way to do this, but hey, I'm in a hurry
- if (gTwoPlayers)
- {
- go = GameObjectAllocate();
- if (! go)
- FatalError("Could not allocate player 2 object.");
-
- GameObjectAddToList(&gPlayerList, go);
-
- SetRect(&r, 20, 0, 620, 0);
- GameObjectSetBounds(go, &r);
- GameObjectSetSprite(go, gSpriteCache[scPlayer2]);
-
- go->kind = objectRedPlayer;
- go->screenX = 640 - 20;
- go->screenY = 412;
- go->velocityH = kPlayerVelocity;
- go->velocityV = 0;
- go->action = RedPlayerAction;
- }
- }
-
- //• -------------------- AddEnemies
-
- static void
- AddEnemies(void)
- {
- Rect r;
- GameObjectPtr go;
- UInt32 i, j;
- UInt32 w, h;
- UInt32 x, x2, y;
-
- gNumEnemies = 0;
-
- //• Find dimensions of enemy sprite so we can center the rows to begin with
- w = SpriteWidth(gSpriteCache[scEnemy], 0);
- w += kEnemyOffset;
- h = SpriteHeight(gSpriteCache[scEnemy], 0);
- h += kEnemyOffset;
-
- x2 = w * kNumEnemyColumns;
- x2 = 320 - (x2 / 2);
-
- y = 100;
-
- SetRect(&r, 20, 20, 620, 400);
-
- for (i = 0; i < kNumEnemyRows; i++)
- {
- x = x2;
-
- for (j = 0; j < kNumEnemyColumns; j++)
- {
- go = GameObjectAllocate();
- if (! go)
- FatalError("Could not allocate enemy object.");
-
- GameObjectAddToList(&gEnemyList, go);
-
- GameObjectSetBounds(go, &r);
- GameObjectSetSprite(go, gSpriteCache[scEnemy]);
-
- go->kind = objectEnemy;
- go->screenX = x;
- go->screenY = y;
- go->velocityH = kEnemyVelocity;
- go->velocityV = 0;
- go->action = EnemyAction;
-
- x += w;
- gNumEnemies++;
- }
-
- y += h;
- }
- }
-
- //• -------------------- AddCDControls
-
- static void
- AddCDControls(void)
- {
- Rect r;
- GameObjectPtr go;
- UInt32 i;
-
- for (i = scPlayButton; i <= scSkipButton; i++)
- {
- go = GameObjectAllocate();
- if (! go)
- FatalError("Could not allocate CD control.");
-
- GameObjectAddToList(&gMiscObjectList, go);
-
- SetRect(&r, 0, 0, 640, 400);
- GameObjectSetBounds(go, &r);
- GameObjectSetSprite(go, gSpriteCache[i]);
-
- go->screenX = RAND(640);
- go->screenY = RAND(240);
- go->velocityH = RAND(2) + 1;
- go->velocityV = RAND(3) + 1;
- go->refCon = i;
- go->action = ObjectBounce;
- }
- }
-
- //• -------------------- AddPoints
-
- static void
- AddPoints(short x, short y)
- {
- Rect r;
- GameObjectPtr go;
-
- go = GameObjectAllocate();
- if (! go)
- FatalError("Could not allocate player shot.");
-
- GameObjectAddToList(&gMiscObjectList, go);
-
- SetRect(&r, 0, 0, 640, 440);
- GameObjectSetBounds(go, &r);
- GameObjectSetSprite(go, gSpriteCache[scPoints]);
-
- go->screenX = x;
- go->screenY = y;
- go->velocityH = 0;
- go->velocityV = kPointsVelocity;
- go->action = PointsAction;
- }
-
- //• -------------------- AddParticles
-
- void
- AddParticles(short x, short y, ObjectKind kind)
- {
- Rect r;
- GameObjectPtr go;
- ParticlesPtr particles;
- UInt8 color;
-
- go = GameObjectAllocate();
- if (! go)
- FatalError("Could not allocate player shot.");
-
- GameObjectAddToList(&gMiscObjectList, go);
-
- SetRect(&r, 0, 0, 640, 400);
- GameObjectSetBounds(go, &r);
- go->frame = 0;
-
- switch (kind)
- {
- case objectEnemyParticles:
- color = kEnemyParticleColor;
- break;
-
- case objectPlayerParticles:
- color = kPlayerParticleColor;
- break;
-
- case objectPlasmaParticles:
- color = kPlasmaParticleColor;
- break;
-
- case objectMissileParticles:
- color = kMissileParticleColor;
- break;
-
- default:
- color = 255;
- }
-
- particles = ParticlesAllocate(x, y, color);
- GameObjectSetParticles(go, particles);
- go->kind = kind;
-
- go->action = ParticleAction;
- }
-
- #pragma mark -
-
- //• -------------------- DisplayFrameRate
-
- static void
- DisplayFrameRate(void)
- {
- static UInt32 lastTime = 0;
- static UInt32 frames = 0;
-
- UInt32 elapsedTime;
- Str255 str;
- GrafPtr oldPort;
- CGrafPtr underlay;
- GDHandle device, oldDevice;
- Rect r;
- UInt32 stringWidth;
-
- //• Initialize the stats at the beginning of each game
- //• gFrameRateBaseTime is reset in InitNewGame()
- if (gFrameRateBaseTime == 0)
- {
- gFrameRateBaseTime = TickCount();
- lastTime = 0L;
- frames = 0L;
- }
-
- //• Bump the frame counter
- frames++;
-
- //• Find the total elapsed time and convert it to seconds
- elapsedTime = TickCount() - gFrameRateBaseTime;
-
- if ( ( elapsedTime - lastTime ) > 120 )
- {
- lastTime = elapsedTime;
- elapsedTime /= 60;
-
- sprintf((char *) str + 1, "FPS: %0.4ld, SSp Load: %ld/%ld", frames / elapsedTime, (gCPULoadMax - gCPUCurrentLoad), gCPULoadMax);
-
- str[0] = strlen ((char *) str + 1);
- stringWidth = StringWidth(str);
-
- GraphicsGetUnderlayGrafPort(&underlay, &device);
-
- GetPort(&oldPort);
- oldDevice = GetGDevice();
-
- SetPort((GrafPtr) underlay);
- SetGDevice(device);
-
- RGBForeColor(&rgbBlack);
- SetRect(&r, 5, 420, 5 + stringWidth, 435);
- PaintRect(&r);
-
- MoveTo(5, 435);
- TextFont(kFontIDGeneva);
- TextFace(0);
- TextSize(9);
-
- RGBForeColor(&rgbYellow);
- DrawString(str);
- RGBForeColor(&rgbBlack);
-
- SetPort(oldPort);
- SetGDevice(oldDevice);
-
- GraphicsSetUnderlayRectDirty(&r);
- }
- }
-
- //• -------------------- DisplayGameOver
-
- static void
- DisplayGameOver(CGrafPtr backBuff)
- {
- GrafPtr oldPort;
- GDHandle oldDevice;
- Str255 str = "\pGame Over!";
- UInt16 width;
- UInt16 offset;
-
- GetPort(&oldPort);
- oldDevice = GetGDevice();
-
- SetGDevice(gGameGDH);
- SetPort((GrafPtr) backBuff);
-
- TextFont(kFontIDGeneva);
- TextFace(bold);
- TextSize(48);
-
- //• Find the width of our string
- width = StringWidth(str);
-
- //• Find an offset that will center the string in the buffer
- offset = backBuff->portRect.right - backBuff->portRect.left;
- offset /= 2;
- offset -= width / 2;
-
- MoveTo(offset, 200);
- RGBForeColor(&rgbYellow);
- DrawString(str);
-
- MoveTo(offset - 2, 200);
- RGBForeColor(&rgbBlue);
- DrawString(str);
-
- MoveTo(offset - 4, 200);
- RGBForeColor(&rgbRed);
- DrawString(str);
-
- RGBForeColor(&rgbBlack);
-
- SetGDevice(oldDevice);;
- SetPort(oldPort);
-
- GraphicsSetRectDirty(&backBuff->portRect);
- }
-
- //• -------------------- EndGame
-
- static void
- EndGame(CGrafPtr backBuff)
- {
- //• Tell InputSprocket to stop watching our devices so that we can use them
- //• for menu command or whatever.
- ISpSuspend();
-
- ShutdownMoviePlayback();
-
- //• Display the "Game Over" banner and pause the graphics system
- DisplayGameOver(backBuff);
- GraphicsUpdateScreen();
- GraphicsPaused();
-
- ShowCursor();
- gGameInProgress = false;
-
- //• Tell network players to shut down
- if (gNetGame)
- {
- Boolean OKHit;
-
- if (gIAmHost)
- gNetState = kHosting;
- else
- gNetState = kJoining;
-
- OKHit = WaitForAllPlayers();
-
- if (OKHit == false)
- ShutdownNetworking();
- else
- {
- gNetState = kStarting;
- SendStartGame();
- InitNewGame(1);
- }
- }
- }
-
- //• -------------------- DoCDAction
-
- static void
- DoCDAction(UInt32 inAction)
- {
- SInt16 currentTrack;
- UInt16 numTracks;
- OSStatus theError;
- UInt16 trackToPlay = 0;
-
- if (false == gCDAudio)
- return;
-
- numTracks = CD_GetNumTracks();
- theError = CD_GetCurrentAudioTrack(¤tTrack);
-
- if (noErr != theError)
- return;
-
- switch (inAction)
- {
- case scPlayButton:
- trackToPlay = 1;
- break;
-
- case scStopButton:
- CD_StopAudioTrack(true);
- break;
-
- case scPrevButton:
- if (currentTrack == 1)
- trackToPlay = numTracks;
- else
- trackToPlay = currentTrack - 1;
- break;
- case scSkipButton:
- if (currentTrack == numTracks)
- trackToPlay = 1;
- else
- trackToPlay = currentTrack + 1;
- break;
- }
-
- if (0 != trackToPlay)
- CD_PlayAudioTrack(trackToPlay, playmodeStereo, true);
- }
-